/*
 * @Author: GYM-png 480609450@qq.com
 * @Date: 2024-10-20 17:59:27
 * @LastEditors: GYM-png 480609450@qq.com
 * @LastEditTime: 2024-10-26 22:23:17
 * @FilePath: \MDK-ARMd:\warehouse\CmdDebug\CmdDebug\UserCode\EasyLogger\elog_port.c
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
/*
 * This file is part of the EasyLogger Library.
 *
 * Copyright (c) 2015, Armink, <armink.ztl@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * 'Software'), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Function: Portable interface for each platform.
 * Created on: 2015-04-28
 */
 
 #include <elog.h>
 #include <stdio.h>
 #include "main.h"
 #include "global.h"
 #include "usart_drv.h"
 #include "config.h"
 #include "FreeRTOS.h"
 #include "task.h"
 #include "semphr.h"
 #include "lwrb.h"
 #include "config.h"
 #include "date.h"
 #include <string.h>
 static SemaphoreHandle_t log_out_mutex = NULL;// 串口互斥锁
 static SemaphoreHandle_t log_rb_mutex = NULL;// lwrb互斥锁
 static lwrb_t log_rb;
 static Date_t date;
 
 /**
  * EasyLogger port initialize
  *
  * @return result
  */
 ElogErrCode elog_port_init(void) {
     ElogErrCode result = ELOG_NO_ERR;
 
     /* add your code here */
     log_out_mutex = xSemaphoreCreateMutex();
     log_rb_mutex = xSemaphoreCreateMutex();
 
     return result;
 }
 
 
 
 /**
  * EasyLogger port deinitialize
  *
  */
 void elog_port_deinit(void) {
 
     /* add your code here */
 
 }
 

 
 /**
  * output log port interface
  *
  * @param log output of log
  * @param size log size
  */
 void elog_port_output(char *log, size_t size) {
     
     /* add your code here */
     elog_port_write_ringbuffer(log, size);
     uart_transmit(DEBUG_UART_INDEX, log, size);
 }
 
 /**
  * output lock
  */
 void elog_port_output_lock(void) {
     
     /* add your code here */
     if( NULL != log_out_mutex )
     {
         xSemaphoreTake(log_out_mutex,portMAX_DELAY);
     }
 }
 
 /**
  * output unlock
  */
 void elog_port_output_unlock(void) {
     
     /* add your code here */
     if( NULL != log_out_mutex )
     {
         xSemaphoreGive(log_out_mutex);
     }
 }
 
 
 /**
  * get current time interface
  *
  * @return current time
  */
 const char *elog_port_get_time(void) {
     
     /* add your code here */
     static char cur_system_time[16] = { 0 };
 
 #if (INCLUDE_xTaskGetSchedulerState  == 1 )
     if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
     {
 #endif
     TickType_t tick = xTaskGetTickCount();
     date_get(&date);
     snprintf(cur_system_time, 16, "%02d:%02d:%02d:%03d",date.hour, date.minute, date.second, tick % 1000);
     return cur_system_time;
 #if (INCLUDE_xTaskGetSchedulerState  == 1 )
     }
 #endif
     return "";
 
 }
 
 /**
  * get current process name interface
  *
  * @return current process name
  */
 const char *elog_port_get_p_info(void) {
     
     /* add your code here */
     return "";
 }
 
 /**
  * get current thread name interface
  *
  * @return current thread name
  */
 const char *elog_port_get_t_info(void) {
     
     /* add your code here */
 #if (INCLUDE_xTaskGetSchedulerState  == 1 )
     if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
     {
 #endif
     return pcTaskGetName(xTaskGetCurrentTaskHandle());
 #if (INCLUDE_xTaskGetSchedulerState  == 1 )
     }
 #endif
     return "";
 }

/**
 * @brief 获取日志缓冲区数据
 *        一次获取多行数据
 * @param[out] out_buf 缓冲区指针
 * @param[in] max_size 最大读取长度
 * @return 实际获取长度
 */
 int elog_port_get_ringbuffer(uint8_t *out_buf, const uint16_t max_size)
 {
    uint16_t r_pr = log_rb.r_ptr;          //临时读取指针
    const uint16_t w_pr = log_rb.w_ptr;    //写入指针 做判断
    const uint16_t rb_size = log_rb.size;  //缓冲区大小
    uint16_t read_size = 0;                 //读取大小
    uint16_t try_size = 0;                  //尝试读取大小
    uint8_t cChar = 0;                      //读取字符
    while (1)
    {
        /*读取字符*/
        cChar = log_rb.buff[r_pr];        
        try_size++;
        r_pr = (r_pr + 1) % rb_size;
        
        /*判断是否超大小*/
        if (try_size >= max_size){          
            break;
        }
        /*缓冲区是否读取完毕*/
        if (r_pr == w_pr && cChar == '\n'){//进这里说明缓冲区已经读取完最后一行并且没有超大小
            read_size = try_size;
            break;
        }
        if (cChar == '\n')//完整读取一行并且没有超大小再才能进行读取
        {
            read_size = try_size;
        }
    }
    xSemaphoreTake(log_rb_mutex, 100);
    read_size = lwrb_read(&log_rb, out_buf, read_size);
    xSemaphoreGive(log_rb_mutex);
    return read_size;
 }

void elog_port_write_ringbuffer(const uint8_t *buf, const uint16_t size)
 {
    xSemaphoreTake(log_rb_mutex, 100);
    lwrb_overwrite(&log_rb, buf, size);
    xSemaphoreGive(log_rb_mutex);
 }

 /*******************************************************************************
 * Function Name  : static_set_output_log_format
 * Description    : 静态设置日志打印格式
 * Input          : None
 * Output         : None
 * Return         : None
 * example        ; log_a("Hello EasyLogger!");		//断言
                    log_e("Hello EasyLogger!");		//错误
                    log_w("Hello EasyLogger!");		//警告
                    log_i("Hello EasyLogger!");		//信息
                    log_d("Hello EasyLogger!");		//调试
                    log_v("Hello EasyLogger!");		//详细
 *******************************************************************************/

 static uint8_t* log_rb_buf = NULL;
 static uint8_t log_ringbuffer[LOG_RINGBUFFER_SIZE] = {0x00};
 void log_init(void)
 {
    lwrb_init(&log_rb, log_ringbuffer, LOG_RINGBUFFER_SIZE);

    elog_init();
    elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_LVL | ELOG_FMT_TIME | ELOG_FMT_TAG);
    elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TIME | ELOG_FMT_TAG);
    elog_set_fmt(ELOG_LVL_WARN, ~ELOG_FMT_ALL);
    elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TIME | ELOG_FMT_TAG);
    elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_DIR));

    elog_set_text_color_enabled(true);
    elog_output_lock_enabled(true);
    /* start EasyLogger */
    elog_start();
 }
 